﻿using Brutalmimi.Core.Ioc;
using Prism.Ioc;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Brutalmimi.Core.Extension
{
    public static class DependencyExtention
    {
        private static List<Type> GetTypes(Assembly assembly)
        {
            var result = assembly.GetTypes()
                .Where(t => t != null && t.IsClass && !t.IsAbstract && t.CustomAttributes
                .Any(c => c.AttributeType == typeof(ExposedServiceAttribute)
                )
                ).ToList();
            return result;
        }
        public static void RegisterAssembly(this IContainerRegistry container, Assembly assembly)
        {
            List<Type> types = GetTypes(assembly);
            foreach (var type in types)
            {
                RegisterType(container,type);
            }
        }
        private static void RegisterType(this IContainerRegistry container, Type type)
        {
            IEnumerable<ExposedServiceAttribute> exposedServiceAttributes = GetExposedServices(type);
            foreach (var item in exposedServiceAttributes)
            {
                if (item.Lifetime == Lifetime.Singleton)
                {
                    container.RegisterSingleton(type);
                }
                foreach (var IType in item.Types)
                {
                    if (item.Lifetime == Lifetime.Singleton)
                    {
                        container.RegisterSingleton(IType, type);
                    }
                    else if (item.Lifetime == Lifetime.Transient)
                    {
                        container.Register(IType, type);
                    }
                }
            }
        }

        public static IEnumerable<ExposedServiceAttribute> GetExposedServices(Type type)
        {
            var typeInfo = type.GetTypeInfo();
            return typeInfo.GetCustomAttributes<ExposedServiceAttribute>();
        }

        public static void InitializeAssembly(this IContainerProvider provider, Assembly assembly)
        {
            Type[] types = assembly.GetTypes();
            foreach (var type in types)
            {
                InitializeType(provider, type);
            }

        }

        private static void InitializeType(IContainerProvider provider, Type type)
        {
            IEnumerable<ExposedServiceAttribute> exposedServiceAttributes = GetExposedServices(type);
            foreach (var item in exposedServiceAttributes)
            {
                if (item.Lifetime == Lifetime.Singleton&&item.AutoInitialize)
                {
                    provider.Resolve(type);
                }
            }

        }

    }
}
